установить - min = 99999
выбрать все бочата в радиусе ....
если расстояние между позиция picked destr и позиция UNIT < min то
установить min - расстояние между ними
установить decor - выбранная декорация
C++ тоже показывает 832.0, на С почему-то не смог запустить. UrsaBoss, вообще, используй нативки, они точнее будут нахождения дистанции "руками" в данном случае. Но не используй Pow(), эта функция очень неточная.
constant native IsUnitInRange takes unit whichUnit, unit otherUnit, real distance returns boolean
constant native IsUnitInRangeXY takes unit whichUnit, real x, real y, real distance returns boolean
constant native IsUnitInRangeLoc takes unit whichUnit, location whichLocation, real distance returns boolean
Нужно внимательнее читать правила. Все проекты, которые видны другим пользователям, проходят премодерацию - модератор должен утвердить вносимые изменения. Обычно это простая формальность и нужно просто дождаться модератора.
Модель открывается в таких редакторах, потому что, вероятно, текстура расположена вместе с моделью в одной папке, а в игре так не проходит - нужен правильный импорт. Чтобы правильно настроить путь к текстуре модели, могу дать такой совет: конвертируй модель из mdx в mdl, через блокнот замени строку к текстуре и конвертируй обратно.
Про области хз, вот именно их разве не через БД лучше, я же не знаю, как в создаваемой карте они называются - Пещера Тысячи Всхлипов или Пляж Огненных Уток...
Тут просто при входе в область писать ее при событии unit входит в область такую-то, легко же вроде даже на гуи...
А так атака ловится через GetUnitBaseDamage сложить с GetUnitGreenBonusDamage.
Скорость атаки через GetUnitAttackSpeed.
Броня через GetUnitArmor (я, правда, пока не мемхаковской пользуюсь, а другой, влом искать, но опытные мапмейкеры знают, если надо - спросить можно).
хпрег через GetUnitHPRegen + мб БД свое.
Мпрег через GetUnitMPRegen + мб БД свое.
Функции эти все тут github.com/DracoL1ch/WC3Memory/blob/master/war3map.j
По импорту мемхака все тут
Даём юниту "липовый" автокаст массового восстановления здоровья ("власть порчи" как у статуи).
Настраиваем, чтобы лечение действовало на кастующего, количество целей указываем 1, восстанавливаемое здоровье - 0.01.
Юнит будет пытаться применить восстановление здоровья(установленный на автокаст) если у него не полное ХП.
При касте именно этого заклинания - заставлять юнит применять каннибализм.
Кароче - стандартный скилл с авто-кастом не переделать в не-автокастовый (но у него есть аналоги без авто каста), а скиллы без авто-каста не переделать в авто-кастовые (только если есть аналог).
Делаешь имитация вручную, через триггеры.
Даёшь юниту "духовное пламя" и в момент его каста - снимаешь бафф и кидаешь даммиком "отравленный нож".
При включении авто-каста добавляешь юниту маркер...
Если марекерованный юнит пытается атаковать кого-либо без баффа отравленного ножа - отдаёшь ему приказ использовать духовное пламя - он в итоге накинет нож...
Это тот же принцип для второго пункта, мне казалось, что могут быть способы изящнее. Лучше по другим пунктам подскажите.
первый вопрос так и не понял, насчет третьего вопроса:
там весь прикол в ивентах, есть начало когда наводишь на цель, тогда даже анимация не проигрывается и мана не забирается.
Приводит в действие это уже когда ману сняло и проигралась анимация.
Где то был текст на всё это, но я не могу найти.
Ну а далее чекаешь уровень бафа у цели, если он больше 0 - значит хиляешь и удаляешь баф
Хотя возможно это я неправильно понял, можно просто отловить начало каста абилки и восстанавливать ману триггерно.
Да сделай проще. Создай многоуровневую способность-пустышку. и когда отдаешь приказ атаковать в область, давай ему эту способность и с помощью неё отслеживай, какую область атаковать.
Например,
способность уровень 1, значит атаковать должен 1 область.
Уровень 2 - 2 область и т. д.
Не вижу смысла усложнять жизнь с хеш-таблицей.
Надеюсь понятно?) Отдал приказ, присвоил способность, после каста жди пару сек и в зависимости от уровня способности-пустышки отправляй в ту или иную область.
не именно пехотинец а вообще любой герой который применяет этот приказ.
это так сказать модификатор атаки будет. мне нужен скил который включается и отключается.
Я уже использовал скилы - Жар преиспобней и Щита маны.
У одного героя может быть 3 модификатора атаки сразу
Приказать ему использовать способность, на основе которой ты делал свою.
Потому что:
При конвертации в JASS данный вариант просто вызовет нативную функцию по отдаче приказа по строке приказа(в русском РО почему-то переведено как "порядок строк"), указанной в скилле(spiritwolf для вызова волка говорящего с духами, например). Этот приказ, кстати, можно менять только для канала(и, быть может, еще чего-то, хотя едва ли). В остальных случаях ничего не изменится, поскольку эта строка вшита в движок. (хотя там, скорее всего, вшит айдишник, НУДАНИВАЖНА).
local rect R = //твоя область
local real x = GetRandomReal(GetRectMinX(R), GetRectMaxX(R))
local real y = GetRandomReal(GetRectMinY(R), GetRectMaxY(R))
Разумеется нет, приказы строго синхронизируются.
Да и как вы себе это представляете? У игрока А работник пошёл рубить лес, а у игрока Б этот же самый работник пошел добывать золото? Что за бред?
Настраиваешь в РО дерево так чтобы у него была 1 вариация и там текстуру нужно к дереву прописать если она импортирована внимательно изучи все строки связанные с деревом как разрушенный объект.
Вариации работают так: в адресе файла модели декорации указывается типа [MyModel].mdx, но этого файла на самом деле нет, а есть только файлы вариации типа [MyModel]0.mdx, [MyModel]1.mdx, [MyModel]2.mdx и т. п.
Только дебаффы ядовитых стрел могут стакатся, но даммик обязан иметь дальнюю атаку (при условии что у разных абилок ядовитых стрел будут разные баффы в настройках).
Так же можно юзать таймер и ауру торнадо как написали выше, ну если уж совсем нужен сложный бафф как дефолтный - то тут триггер и немного гемора с мемхаком, зато полный комплект параметров (мигает иконка в статусе перед завершением время действия, бафф спадает с цели после диспела, смерти (у цели крест перерождения или аналог), складывается или не складывается в зависимости от кода).
Пример не рекомендуемый к повторению
function FormatAirportTrainingBar takes integer fp_n returns string
local string str = ""
if ( fp_n <= 0 ) then
return str
endif
loop
exitwhen fp_n < 10
if ( udg__TempBarStyle == 0 ) then
set str = str + "''''''''''"
else
set str = str + "||||||||||||||||||||"
endif
set fp_n = fp_n - 10
endloop
loop
exitwhen fp_n <= 0
if ( udg__TempBarStyle == 0 ) then
set str = str + "'"
else
set str = str + "||"
endif
set fp_n = fp_n - 1
endloop
return str
endfunction
function UpdateAirportTrainingBar takes texttag tt, integer fp_nTick, integer fp_nTickMax returns nothing
local integer nProgress
local integer nLen
local string strTT1
local string strTT2
if ( tt == null ) then
call BJDebugMsg( "text tag hDZzRwuZxFQcXqaMPnML null" )
return
endif
set nLen = R2I( I2R( fp_nTickMax ) / 300 * 100 )
set nProgress = R2I( I2R( nLen ) / fp_nTickMax * fp_nTick )
set strTT1 = "" + FormatAirportTrainingBar( nProgress )
set strTT2 = FormatAirportTrainingBar( nLen - nProgress ) + ""
call SetTextTagText( tt, "|cff0080c0" + strTT1 + "|r|cffff0000" + strTT2 + "|r", 0.023 )
endfunction
function Get_Staff_of_Purification takes unit runner returns item
set bj_forLoopAIndex = 0
set bj_lastCreatedItem = null
if GetUnitAbilityLevel( runner, 'Arun' ) == 0 then
return null
endif
loop
exitwhen bj_forLoopAIndex > 5
set bj_lastCreatedItem = UnitItemInSlot( runner, bj_forLoopAIndex )
if GetItemTypeId( bj_lastCreatedItem ) == 'I01A' then
return bj_lastCreatedItem
endif
set bj_forLoopAIndex = bj_forLoopAIndex + 1
endloop
return bj_lastCreatedItem
endfunction
function Trig_RunnerDamageDetect_Conditions takes nothing returns boolean
if GetTriggerEventId( ) == EVENT_UNIT_DAMAGED then
return GetEventDamage( ) > 0.00 and GetEventDamageSource( ) != GetTriggerUnit( ) and GetEventDamageSource( ) != DummyAttacker
endif
return true
endfunction
function HealRunner takes nothing returns nothing
local DamageData dd = GetDataBX( GetExpiredTimer( ) )
call UnitRemoveAbility( dd.attacked, 'AMhp' )
call SetUnitState( dd.attacked, UNIT_STATE_LIFE, dd.hp )
call RemoveDataBX( dd.trix )
call DestroyTimer( dd.trix )
call dd.clear( )
call dd.destroy( )
endfunction
function Trig_RunnerDamageLock_Actions takes nothing returns nothing
local TriggerData st = GetDataBX( GetTriggeringTrigger( ) )
local DamageData dd
local eventid id = GetTriggerEventId( )
if id == EVENT_GAME_TIMER_EXPIRED and st.id < st.time and st.attacked != null then
set st.id = st.id + 1
if GetUnitAbilityLevel( st.attacked, 'Bcyc' ) > 0 or GetUnitAbilityLevel( st.attacked, 'Bcy2' ) > 0 then
call SetTextTagPos( st.tt, GetUnitX( st.attacked ) - 60.00, GetUnitY( st.attacked ) - 60.00, 585.00 )
else
call SetTextTagPos( st.tt, GetUnitX( st.attacked ) - 60.00, GetUnitY( st.attacked ) - 60.00, 80.00 + GetUnitFlyHeight( st.attacked ) )
endif
call UpdateAirportTrainingBar( st.tt, 100 - R2I( st.dmg / st.hp * 100.00 ), 100 )
elseif id == EVENT_UNIT_DAMAGED and st.dmg < st.hp then
set dd = DamageData.create( )
set dd.trix = CreateTimer( )
set dd.attacked = st.attacked
set dd.dmg = GetEventDamage( )
set dd.hp = GetUnitState( dd.attacked, UNIT_STATE_LIFE )
call SetDataBX( dd.trix, dd )
call UnitAddAbility( dd.attacked, 'AMhp' )
call SetUnitState( dd.attacked, UNIT_STATE_LIFE, dd.hp + dd.dmg )
call TimerStart( dd.trix, 0.00, false, function HealRunner )
set st.dmg = st.dmg + dd.dmg
else
call UnitRemoveAbility( st.attacked, 'A08L' )
call UnitMakeAbilityPermanent( st.attacked, false, 'A08L' )
call DisableTrigger( st.trg )
call SetTextTagVisibility( st.tt, false )
if not IsUnitDead( st.attacked ) then
call UnitRemoveAbility( st.attacked, 'B00A' )
endif
call RemoveSavedInteger( gg_htb_HashData, ExKeySoPRunner, GetHandleId( st.attacked ) )
call st.RemoveTrigger( )
call st.destroy( )
endif
set id = null
endfunction
function Trig_Staff_of_Purification_Actions takes nothing returns nothing
local TriggerData dd
local unit Runner = GetSpellAbilityUnit( )
local integer RunnerId = GetHandleId( Runner )
local item Staff = LoadItemHandle( gg_htb_HashData, RunnerId, ExKeySoP )
local integer ChargesCount = 0
local trigger trig = LoadTriggerHandle ( gg_htb_HashData, ExAtomShield, RunnerId )
local integer pBuff
if Staff == null then
set Staff = Get_Staff_of_Purification( Runner )
if Staff == null then
//call DisplayTextToPlayer( Player( CrashPlayerNumber ), 0.00, 0.00, I2Sx( 'A01Q', CrashPlayerNumber ) )
call BJDebugMsg( DEBUG + I2Sx( 'A02O', 0 ) + INFO )
return
endif
call SaveBoolean( gg_htb_HashData, RunnerId, ExKeyHasStaff, true )
call SaveItemHandle( gg_htb_HashData, RunnerId, ExKeySoP, Staff )
endif
set ChargesCount = GetItemCharges( Staff )
if ChargesCount < 1 then
set Runner = null
set Staff = null
set trig = null
return
endif
call SetItemCharges( Staff, 0 )
if trig != null then // блокирующие урон способности не складываются.
call TriggerExecute( trig )
set trig = null
endif
set dd = TriggerData.create( )
set dd.attacked = Runner
set dd.pl = GetOwningPlayer( Runner )
set dd.trg = CreateTrigger( )
set dd.trc = TriggerAddCondition( dd.trg, Condition( function Trig_RunnerDamageDetect_Conditions ) )
set dd.tra = TriggerAddAction ( dd.trg, function Trig_RunnerDamageLock_Actions )
set dd.tt = CreateTextTag( )
set dd.hp = 1000.00 * ChargesCount
set dd.dmg = 1.00
set dd.id = 0
set dd.time = 480
set dd.c = 0.03125
call UnitAddAbility( Runner, 'A07E' )
call UnitRemoveAbility( Runner, 'A07E' )
call UnitAddAbility( Runner, 'A08L' )
call UnitMakeAbilityPermanent( Runner, true, 'A08L' )
call SetDataBX( dd.trg, dd )
call SaveInteger( gg_htb_HashData, ExKeySoPRunner, RunnerId, dd )
call TriggerRegisterPlayerEvent( dd.trg, dd.pl, EVENT_PLAYER_LEAVE )
call TriggerRegisterDeathEvent( dd.trg, Runner )
call TriggerRegisterUnitEvent( dd.trg, Runner, EVENT_UNIT_DAMAGED )
call TriggerRegisterTimerEvent( dd.trg, 0.03125, true )
if GetLocalPlayer( ) == dd.pl or IsPlayerAlly( GetLocalPlayer( ), dd.pl ) then
call SetTextTagVisibility( dd.tt, true )
else
call SetTextTagVisibility( dd.tt, false )
endif
set pBuff = GetUnitAbility( dd.attacked, 'B00A' ) + 0x90
set dd.c = TimerGetElapsed( DispTimer )
call WMem( RMem( pBuff ) + 0x4, mR2I( dd.c + 15.10 ) )
call WMem( RMem( pBuff ) + 0x8, mR2I( dd.c + 10.408 ) )
call SetBuffLevel( pBuff - 0x90, ChargesCount )
call UpdateAirportTrainingBar( dd.tt, 100, 100 )
set Runner = null
endfunction
//===========================================================================
function InitTrig_Staff_of_Purification takes nothing returns nothing
set udg__TempBarStyle = 0
endfunction
Выше пример баффа для предмета, который образует щит блокирующий урон, кол-во заблокированного урона и сколько еще заблокирует щит отображается над головой героя, в виде полоски здоровья (только цвет сине-красный). Так же в статуе есть бафф, один в 1 как бафф дефектных способностей вара, не складывается - новый, перебивает старый. И так далее...
function move takes integer i returns nothing
local unit u = udg_unit[i] // дамми снаряда
local location p = GetUnitLoc(u)
local location p2 = udg_point[i] // таргет спелла
local real a
if DistanceBetweenPoints(p, p2) > 100 then
set a = AngleBetweenPoints(p, p2)
call MoveLocation(p, GetLocationX(p) + 10 * CosBJ(a), GetLocationY(p) + 10 * SinBJ(a))
call SetUnitPositionLoc( u, p )
else
call KillUnit( u )
call RemoveLocation(p2)
set udg_unit[i] = udg_unit[udg_number]
set udg_point[i] = udg_point[udg_number]
set udg_i = udg_i-1
set udg_number = udg_number -1
call PolledWait(0.5)
call RemoveUnit(u)
endif
set u = null
call RemoveLocation(p)
set p = null
set p2 = null
set a = 0
endfunction
глобальный массив не нужен. сохраняй группу в хэш-таблицу на хэндл героя, потом загружай ее когда надо. у каждого героя будет своя группа
вот пример, молот бурь съедает юнита а удар грома ставит всех юнитов обратно
cJass, vJass и Jass2 - разные концы одной палки. Но после освоения структур, которые есть в vJass и освоения синтаксиса cJass ты вполне сможешь быстро освоить любой язык C-семейства.
Наверное, имеется ввиду, что при движении камеры в диалогах могут пропадать модели, середину которых камера не захватывает. Мне тоже интересен этот вопрос. Сам пока не разбирался, но есть предположение, что модель может перестать исчезать, если сделать её какой-то разновидностью декораций.
Ну у мастера клинка способность то посложнее...
Вот пример:
Для начала нам нужно создать иллюзии героя, а потом скрыть всех их, так же сделав визуальный эффект (если что то зеленые тени, это снаряды).
Filius Dei, у канал есть пунктик "изображение". Если этот пунктик галочкой снять, то изображение иконки не будет отображаться. Но можно отдавать приказы через триггеры.
Можно сделать двухуровневую способность, в одном уровне иконка скрыта, в другом показана (но не пробовал такое)
Короче, поскольку кроме костылей ни вы, ни я ничего придумать не решили, вот моя реализация:
Герою дается двойной инвиз(не выходит из него при атаках и кастах), для всех игроков создается дамми с трусайтом с минимальным радиусом, с привязкой к владельцу кастера(по номеру игрока), и его двигает таймером за юнитом. Дамми НЕ создается для тех игроков, которые попали под иллюзию. Также им отключается шейрвижен, чтобы союзники НЕ попавшие в иллюзию, не палили кастера своей дамми-трусайтом.
Проще говоря, вместо того, чтобы дать инвиз против отдельных игроков, я дал всем игрокам трусайт, и только зацепленным - нет.
массивы или хэш
один фиг
только массивы быстрее
массивы надо знать обязательно
они используются не только в программировании но и в математике и физике
та же хэш таблица построена на основе массива
всегда по ссылке для handle-типов, всегда по значению для остальных
изменить это невозможно
никак, использовать глобалку, куда сохранять локалку перед нулением
нет, нету
ну или аналоги всего этого есть в продвинутых редакторах, не знаю, пусть те, кто ими пользуются, скажут
Неуязвимость проверяют через даммика с атакой, через приказ, сможет ли атаковать или нет, просто проверка выполнения приказа. Так же пытаются нанести урон и смотрят сколько он отнял здоровья, так можно и определить неуязвимость и вычислить резист юнита к конкретному типу урона.
максимальная длина массива 8192
ты врёшь
хотя бы потому что нельзя нормально устанавливать длину массива(можно лишь увеличить его размер ещё на 8192,но это только в сиджасс)
короче размер массива фиксирован
Ige, да о чем вы говорите. ИМХО, самое оптимальное предложение содержится в 3 комментарии.
И еще тут много лишних функций. Да и просто первый признак jass - отсутствие бж за исключением дебага( хоть мои слова кажется трепом и выпендрежем, но без чистого скрипта на нативах.... )
Это число обозначает, сколько элементов массива заполняется в начале игры значением по умолчанию. Настоящий размер массива всегда 8192.
Т.е. если ты ставишь "Раз. 3" и "Нач. знач. 1", то первые 3 элемента массива будут равны 1, а значение следующих будет неопределенным.
Вобщем озарение как всегда пришло внезапно - понял что GetSpellAbilityUnit срабатывает на дамми и записывает в массив его, а не цель щита. Просто передвинул махинации с дамми в конец функции Actions. Всё отменно работает. Всем спасибо все свободны
Очередной проект задохнулся за недостатком энтузиазма...
Ну почему же сразу "задохнулся"? АоС как жанр в целом может развиваться бесконечно, и любую версию после релизной можно воспринимать как финальную, пока не выйдет следующая.
Автору: вообще-то говоря, подобные вещи обычно публикуют в блогах. В QA (этом разделе) тоже можно, конечно, но вопросы обычно очень быстро пропадают из поля зрения пользователей сайта, а поиск продолжателя может занять значительное время. Вообще, я бы глянул исходник интереса ради. Продолжать гарантированно не буду, но мб на досуге что-нибудь запилю/перепилю для развлечения и скину тебе. Впрочем, тоже не обещаю.
Остальных комментаторов хотелось бы попросить воздержаться от выкрикивания мнений без конструктива по существу.
А еще у меня там местами xpcall отладочный висит, там где я ловил косяки и не убрал его потом, без него код чуть проще становится, он нужен только для отлова ошибок и в моем случае вывода их на экран.
Это печально, новые костыли, а я уже обрадовался, что ничего обнулять и чистить не нужно =(
Не нужно обнулять локалки в функциях и все что ограниченного срока жизни, но всякие системы хранения данных они же либо глобальные либо в "локальном" скопе всей карты и, соответственно, живут пока загружена карта - там вручную подчищать надо, естественно. Можно делать это полу-автоматически как у меня, можно вручную когда становится известно что данные уже не нужны. Можно было бы использовать таблицу со слабыми ключами, но тогда возникает вопрос что использовать в качестве ключей - можно прямо на самого юнита вешать, чтобы когда игра его удалит из памяти, таблица почистилась сборщиком мусора, но нет гарантии что это будет работать и не будет вызывать десинки т.к. сборщику мусора синхронизация не указ. Bergi_Bear:
но мне можно себе такой вариант забрать или надо ещё что-то дополнительно записать?
У меня библиотека отгорожена только ради того чтобы автоматизировать сборку мусора и создание новых таблиц при обращении по хендлу на который ничего нет.
Минимальный вариант, наверно, такой:
local HandleData = {} -- я использую локальные переменные в скопе карты, при этом важен порядок но доступ к ним идет чуть быстрее чем в глобальном скопе
function ForceUnit (u,a,d,s,flag)
local data = HandleData[GetHandleId(u)]
if (data==nil) then data = {} HandleData[GetHandleId(u)] = data end
data.a = a
data.d = d
data.s = s
data.flag = flag
GroupAddUnit(gforce, u)
end
-- --------------
ForGroup(gforce, function()
local u=GetEnumUnit()
local h=GetHandleId(u)
local data = HandleData[h]
local a=data.a
local d=data.d
local s=data.s
local flag=data.flag
...
end
» WarCraft 3 / Юниты не перестают появляться
» WarCraft 3 / Уровень моба
» WarCraft 3 / Приказ Группе jass
» Администрация XGM / Модерирование проектов
» Администрация XGM / Баги
» WarCraft 3 / Юниты не всегда кастуют
» WarCraft 3 / Проблема с компанией.
» WarCraft 3 / Название переменной на Jass
» WarCraft 3 / Доступность исследования
» WarCraft 3 / Как сделать способности автокаст?
» WarCraft 3 / Создание юнита из 2 других.
» WarCraft 3 / Приказ юниту
» Администрация XGM / Смена никнейма
» WarCraft 3 / Импорт деревев
» WarCraft 3 / Дамми не кастует спелл
» WarCraft 3 / Локальные переменные и таймер
» WarCraft 3 / Декорация пропадает
» WarCraft 3 / Функция сообщения от игрока
» WarCraft 3 / Вопросы по Lua
» WarCraft 3 / Скрыть способность юнита
» WarCraft 3 / Локальный массив Jass
» WarCraft 3 / Не создаётся предмет
» WarCraft 3 / Длина массива.
» WarCraft 3 / Событие - игрок ливает
» WarCraft 3 / Принципы Jass